package com.elitecrm.webchat.logic;

import com.elitecrm.webchat.dao.cache.SyscParameterCache;
import com.elitecrm.webchat.util.MergeUtil;
import com.elitecrm.webchat.util.StringUtil;
import com.elitecrm.webchat.util.db.DbUtil;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;
import java.util.Map;
import java.util.UUID;

public class UserIpInterceptor
        implements UserInterceptor
{
    private static final Logger log = LoggerFactory.getLogger(UserIpInterceptor.class);

    public boolean intercept(Map<String, Object> userInfo, String epid)
    {
        try
        {
            String ip = StringUtil.parseNull(userInfo.get("proxyIp"));
            log.debug("ip : " + ip);
            String proxyIp = StringUtil.parseNull(userInfo.get("ip"));
            log.debug("proxyIp: " + proxyIp);

            JdbcTemplate jt = DbUtil.getJdbcTemplate(epid);
            String sql = MergeUtil.mergeEpid("SELECT * FROM CHAT_IP_BLACKLIST${EPID} WHERE IP = ? AND (VALIDITY >? OR VALIDITY = -1)", epid);
            List resultList = jt.queryForList(sql, new Object[] { ip, Long.valueOf(System.currentTimeMillis()) });
            if (resultList.size() > 0) {
                log.debug("ip " + ip + " is in black list.");
                return true;
            }

            String guid = UUID.randomUUID().toString();
            sql = MergeUtil.mergeEpid("INSERT INTO CHAT_IP_VISIT_HIS${EPID}(GUID, IP, PROXY_IP, CREATION_TIME) VALUES(?, ?, ?, ?)", epid);
            jt.update(sql, new Object[] { guid, ip, proxyIp, Long.valueOf(System.currentTimeMillis()) });

            long checkIpTimeThreshold = 60000L;
            int checkIpCountThreshold = 10;
            long blacklistValidityElasped = 3600000L;
            try {
                String IPBPAR = SyscParameterCache.findSyscParameterById("IPBPAR", epid);
                if (StringUtil.isNotNull(IPBPAR)) {
                    JSONObject ipBlackParamJSON = JSONObject.fromObject(IPBPAR);
                    long checkIpTimeThresholdParam = ipBlackParamJSON.optLong("checkIpTimeThreshold");
                    if (checkIpTimeThresholdParam > 0L) {
                        checkIpTimeThreshold = checkIpTimeThresholdParam * 1000L;
                    }
                    int checkIpCountThresholdParam = ipBlackParamJSON.optInt("checkIpCountThreshold");
                    if (checkIpCountThresholdParam > 0) {
                        checkIpCountThreshold = checkIpCountThresholdParam;
                    }
                    long blacklistValidityElaspedParam = ipBlackParamJSON.optLong("blacklistValidityElasped");
                    if (blacklistValidityElaspedParam < 0L)
                        blacklistValidityElasped = -1L;
                    else if (blacklistValidityElaspedParam > 0L)
                        blacklistValidityElasped = blacklistValidityElaspedParam * 1000L;
                }
            }
            catch (Exception e) {
                log.error("", e);
            }
            log.debug("checkIpTimeThreshold: " + checkIpTimeThreshold + "    checkIpCountThreshold: " + checkIpCountThreshold + "    blacklistValidityElasped: " + blacklistValidityElasped);

            long checkCreationTime = System.currentTimeMillis() - checkIpTimeThreshold;

            int recentVisitCount = ((Integer)jt.queryForObject(MergeUtil.mergeEpid("SELECT COUNT(*) FROM CHAT_IP_VISIT_HIS${EPID} WHERE IP=? AND CREATION_TIME>?", epid), Integer.class, new Object[] { ip,
                    Long.valueOf(checkCreationTime) })).intValue();

            if (recentVisitCount >= checkIpCountThreshold) {
                log.debug("IP " + ip + " recent visit count " + recentVisitCount + ", which has reach the limit count " + checkIpCountThreshold + " in " + checkIpTimeThreshold + "ms.");
                String blacklistGuid = UUID.randomUUID().toString();
                long validity = System.currentTimeMillis() + blacklistValidityElasped;

                int affectCount = jt.update(MergeUtil.mergeEpid("UPDATE CHAT_IP_BLACKLIST${EPID} SET VALIDITY = ? WHERE IP= ?", epid), new Object[] { Long.valueOf(validity), ip });
                if (affectCount == 0) {
                    jt.update(MergeUtil.mergeEpid("INSERT INTO CHAT_IP_BLACKLIST${EPID}(GUID, IP, VALIDITY) VALUES(?,?,?)", epid), new Object[] { blacklistGuid, ip, Long.valueOf(validity) });
                    log.debug("Add ip " + ip + " to BLACKLIST");
                } else {
                    log.debug("Update ip " + ip + " VALIDITY FROM BLACKLIST");
                }
                return true;
            }
        } catch (Exception e) {
            log.error("", e);
        }
        return false;
    }
}